import type { ImageInfoExtractorConfig } from '../../../lib/document_operator/triggers/image_info_extractor'
import type { ComponentStyleIdType, PlatformTypeValue } from '../../../types/interfaces'
import { BaseModule } from '../../../lib/abstract'
import { ImageInfoExtractor } from '../../../lib/document_operator/triggers/image_info_extractor'
import { ICON_IDS } from '../../../lib/icons/types/constants'
import { ImageHandler } from '../../../lib/image_handler'
import { PageHandler } from '../../../lib/page_handler'
import {
  BIAN_LIST_ITEM_SELECTOR,
  BianPageType,
} from '../../../lib/page_handler/platform/bian/types'
import { ToolKit } from '../../../lib/utils/toolkit'
import {
  BodyAttrs,
  ComponentStyleId,
  HOSTNAME,
  logger,
  SUPPORTED_PLATFORMS,
  TIME_UNITS,
} from '../../../types/constants'
import { ConfigManager } from '../../config_manager'

export interface ImageDetailConfig {
  selector: string
  imageSelector: string
  titleSelector: string
  detailSelector: {
    url: string
    size: string
    bulk: string
  }
}
export type ImageDetailPlatformConfig = Partial<Record<PlatformTypeValue, Record<string, ImageDetailConfig>>>

interface Config {
  enabled?: boolean
  fetchConfig: {
    timeout: number
    retryCount: number
  }
  performance: {
    cacheTtl: number // 缓存生存时间（毫秒）
    maxConcurrentFetches: number // 最大并发请求数
    debounceDelay: number // 防抖延迟（毫秒）
    throttleDelay: number // 节流延迟（毫秒）
    preloadBatchSize: number // 预加载批次大小
  }
}

export class ImageDetail extends BaseModule {
  // @Decorators.Identity
  readonly id: string = 'image_detail'
  get name(): ComponentStyleIdType {
    return 'ImageDetail'
  }

  // @Decorators.InheritedConfig
  readonly styleId: string = ComponentStyleId[this.name]
  readonly supportedPlatforms: string[] = ConfigManager.getInstance().moduleSupportedPlatforms(this.name)
  // @Decorators.PublicState
  isInitialized: boolean = false
  private static instance: ImageDetail
  // @Decorators.Dependency
  private readonly imageHandler: ImageHandler = ImageHandler.getInstance()
  private readonly imageInfoExtractor: ImageInfoExtractor = new ImageInfoExtractor()
  // @Decorators.UIElement
  private readonly PROCESSED_ATTR: string = `${BodyAttrs.PROCESSED_ELEMENT}-image-detail`
  // @Decorators.Config
  // 需要过滤掉的多余内容正则表达式（注意先后顺序的影响）
  private readonly REDUNDANT_TEXT_PATTERNS = [
    /4k([^壁纸]*)壁纸/gi,
    /4k/gi,
    /竖屏/g,
    /高清/g,
    /\d+[x×*]\d+/gi, // 所有尺寸格式：1920x1080
    /\d+\s*[x×*]\s*\d+/gi, // 带空格的尺寸：1920 x 1080
    /\d+px?\s*[x×*]\s*\d+px?/gi, // 带px的尺寸：1920px x 1080px
    /分辨率[：:]\s*\d+[x×*]\d+/gi, // 分辨率：1920x1080
    /尺寸[：:]\s*\d+[x×*]\d+/gi, // 尺寸：1920x1080
    /宽度?[：:]\s*\d.*高度?[：:]\s*\d+/g, // 宽度：1920 高度：1080
    /\s+/g, // 多个连续空格（替换为单个空格）
    /^[|｜]/g, // 开头的 | 或 ｜
  ]

  get currentConfig(): ImageDetailConfig | undefined {
    return this.getCurrentConfig()
  }

  // @Decorators.TemporaryState
  private imageInfoCache: Map<string, {
    size: string
    bulk: string
    timestamp: number
    status: 'pending' | 'success' | 'error'
  }> = new Map() // 图片信息缓存

  private activeFetches: Set<string> = new Set() // 正在进行的获取请求
  private lastHoverTimes: Map<string, number> = new Map() // 最后悬浮时间（用于节流）

  config: Config = {
    enabled: true,
    fetchConfig: {
      timeout: 10000,
      retryCount: 1,
    },
    performance: {
      cacheTtl: TIME_UNITS.COMMON.INTERVALS.HALF_HOUR,
      maxConcurrentFetches: 3,
      debounceDelay: 500,
      throttleDelay: 100, // 节流延迟（毫秒）
      preloadBatchSize: 5,
    },
  }

  /**
   * 获取单例实例
   */
  public static getInstance(): ImageDetail {
    if (!ImageDetail.instance) {
      ImageDetail.instance = new ImageDetail()
    }
    return ImageDetail.instance
  }

  handleCleanupReferences(): void {
    this.imageInfoCache.clear()
    this.activeFetches.clear()
    this.lastHoverTimes.clear()
  }

  handleCleanupOthers(): void {
    this.unregisterStyle(this.styleId)

    if (!this.currentConfig)
      return

    const { selector, titleSelector } = this.currentConfig

    // 移除处理标识
    const $container = $(selector)
    const $title = $container.find(`${titleSelector}[${this.PROCESSED_ATTR}='true']`)
    const originalText = $title.attr('data-original-text') || ''

    $container.removeAttr(this.PROCESSED_ATTR)
    $title
      .removeClass('loading')
      .text(originalText)
      .removeAttr(this.PROCESSED_ATTR)
      .removeAttr('data-original-text')
  }

  core(): void {
    this.loadConfig()

    if (!this.config.enabled)
      return

    this.applyToImages()

    // 注册样式
    this.registerStyle(this.styleId, this.getStyles())

    // 启动预加载
    this.startPreloading()
  }

  onToggleCallback(_id: string, checked: boolean, first: boolean): void {
    super.onToggleCallback(_id, checked, first)
  }

  /**
   * 获取当前页面的配置
   */
  getCurrentConfig(): ImageDetailConfig | undefined {
    const config: ImageDetailPlatformConfig = {
      [SUPPORTED_PLATFORMS.BIAN]: {
        [BianPageType.List]: {
          selector: BIAN_LIST_ITEM_SELECTOR,
          imageSelector: 'a > img',
          titleSelector: 'a > b',
          detailSelector: {
            url: 'a:has(img)',
            size: '.side .infor p:contains("尺寸") span',
            bulk: '.side .infor p:contains("体积") span',
          },
        },
      },
    }

    const currentConfig = config[HOSTNAME]?.[PageHandler.getCurrentPageType()]

    if (!currentConfig) {
      logger.warn(`[${this.name}] 未找到当前页面类型的配置`)
    }

    return currentConfig
  }

  /**
   * 启动预加载
   */
  private startPreloading(): void {
    if (!this.currentConfig)
      return

    const { selector, detailSelector } = this.currentConfig
    const $containers = $(selector)
    const preloadBatchSize = this.config.performance.preloadBatchSize

    // 收集前 N 个图片的详情页 URL 用于预加载
    const urlsToPreload: string[] = []

    $containers.each((_index, container) => {
      if (urlsToPreload.length >= preloadBatchSize)
        return false

      const $container = $(container)
      const $detailLink = $container.find(detailSelector.url)
      const detailUrl = $detailLink.attr('href')

      if (detailUrl && !this.imageInfoCache.has(detailUrl)) {
        urlsToPreload.push(detailUrl)
      }
    })

    // 异步预加载
    this.preloadImageInfo(urlsToPreload).then(() => {
      logger.important(`[${this.name}] 预加载完成`, { urls: urlsToPreload })
    })
  }

  /**
   * 预加载图片信息
   */
  private async preloadImageInfo(urls: string[]): Promise<void> {
    if (urls.length === 0)
      return

    const maxConcurrent = this.config.performance.maxConcurrentFetches

    // 分批处理，控制并发数
    for (let i = 0; i < urls.length; i += maxConcurrent) {
      const batch = urls.slice(i, i + maxConcurrent)
      await Promise.allSettled(
        batch.map(url => this.preloadSingleImageInfo(url)),
      )

      // 批次间延迟，避免过于密集的请求
      await new Promise(resolve => setTimeout(resolve, 100))
    }
  }

  /**
   * 预加载单个图片信息
   */
  private async preloadSingleImageInfo(detailUrl: string): Promise<void> {
    // 检查缓存和正在进行的请求
    if (this.imageInfoCache.has(detailUrl) || this.activeFetches.has(detailUrl))
      return

    try {
      this.activeFetches.add(detailUrl)

      // 设置缓存为 pending 状态
      this.imageInfoCache.set(detailUrl, {
        size: '',
        bulk: '',
        timestamp: Date.now(),
        status: 'pending',
      })

      const imageInfo = await this.fetchImageInfoFromDetailPage(detailUrl)

      // 更新缓存
      this.imageInfoCache.set(detailUrl, {
        ...imageInfo,
        timestamp: Date.now(),
        status: 'success',
      })

      logger.debug(`[${this.name}] 预加载成功`, { url: detailUrl })
    }
    catch (error) {
      // 标记为错误状态，避免重复尝试
      this.imageInfoCache.set(detailUrl, {
        size: '',
        bulk: '',
        timestamp: Date.now(),
        status: 'error',
      })

      logger.debug(`[${this.name}] 预加载失败`, {
        url: detailUrl,
        error: error instanceof Error ? error.message : String(error),
      })
    }
    finally {
      this.activeFetches.delete(detailUrl)
    }
  }

  private applyToImages(): void {
    if (!this.currentConfig)
      return

    const { selector } = this.currentConfig
    const $containers = $(selector)

    $containers.each((_index, container) => {
      this.attachToContainer($(container))
    })
  }

  /**
   * 为单个容器添加悬浮事件
   */
  private attachToContainer($container: JQuery<Element>): void {
    // 检查是否已处理
    if ($container.attr(this.PROCESSED_ATTR))
      return

    const { detailSelector } = this.currentConfig!
    const $detailLink = $container.find(detailSelector.url)

    // 获取详情页链接
    const detailUrl = $detailLink.attr('href')

    if (!detailUrl) {
      logger.warn(`[${this.name}] 未找到详情页链接`)
      return
    }

    // 添加悬浮事件
    this.setupHoverEvents($container, detailUrl)

    // 标记为已处理
    $container.attr(this.PROCESSED_ATTR, 'true')
  }

  /**
   * 设置悬浮事件
   */
  private setupHoverEvents($container: JQuery<Element>, detailUrl: string): void {
    const { throttleDelay } = this.config.performance

    const mouseEnterHandler = () => {
      // 节流控制：避免过于频繁的悬浮
      const lastHoverTime = this.lastHoverTimes.get(detailUrl) || 0
      const now = Date.now()

      if (now - lastHoverTime < throttleDelay) // 一定时间内不处理新悬浮
        return

      this.lastHoverTimes.set(detailUrl, now)
      this.debouncedFetchData(detailUrl, $container)
    }

    const mouseLeaveHandler = () => {
    }

    $container
      .on('mouseenter.imageDetail', mouseEnterHandler)
      .on('mouseleave.imageDetail', mouseLeaveHandler)

    this.tracker.eventListeners($container, 'mouseenter.imageDetail', mouseEnterHandler)
    this.tracker.eventListeners($container, 'mouseleave.imageDetail', mouseLeaveHandler)
  }

  /**
   * 获取图片数据（防抖处理）
   */
  private debouncedFetchData = ToolKit.func.debounce(async (detailUrl: string, $container: JQuery<Element>) => {
    // 切换标题为加载中
    this.toggleImageTitleStatus($container, true)
    await this.fetchAndUpdateImageInfo($container, detailUrl)
  }, this.config.performance.debounceDelay)

  /**
   * 获取图片信息并更新标题
   */
  private async fetchAndUpdateImageInfo($container: JQuery<Element>, detailUrl: string): Promise<void> {
    const cacheTtl = this.config.performance.cacheTtl
    const now = Date.now()

    // 检查缓存（包含 TTL 验证）
    const cachedInfo = this.imageInfoCache.get(detailUrl)
    if (cachedInfo) {
      // 检查缓存是否过期
      if (now - cachedInfo.timestamp < cacheTtl && cachedInfo.status === 'success') {
        this.updateTitleWithImageInfo($container, cachedInfo.size, cachedInfo.bulk)
        return
      }

      // 检查是否正在获取
      if (cachedInfo.status === 'pending') {
        this.toggleImageTitleStatus($container, true)
        return
      }
    }

    // 检查是否正在获取
    if (this.activeFetches.has(detailUrl)) {
      this.toggleImageTitleStatus($container, false)
      return
    }

    try {
      // 设置缓存为 pending 状态
      this.imageInfoCache.set(detailUrl, {
        size: '',
        bulk: '',
        timestamp: now,
        status: 'pending',
      })

      const imageInfo = await this.fetchImageInfoFromDetailPage(detailUrl)

      if (imageInfo.size || imageInfo.bulk) {
        this.imageInfoCache.set(detailUrl, {
          ...imageInfo,
          timestamp: now,
          status: 'success',
        })

        this.updateTitleWithImageInfo($container, imageInfo.size, imageInfo.bulk)

        logger.debug(`[${this.name}] 图片信息获取成功`, {
          size: imageInfo.size,
          bulk: imageInfo.bulk,
          url: detailUrl,
        })
      }
    }
    catch (error) {
      // 标记为错误状态
      this.imageInfoCache.set(detailUrl, {
        size: '',
        bulk: '',
        timestamp: now,
        status: 'error',
      })

      logger.warn(`[${this.name}] 获取图片信息失败`, {
        url: detailUrl,
        error: error instanceof Error ? error.message : String(error),
      })
      throw error
    }
    finally {
      this.toggleImageTitleStatus($container, false)
    }
  }

  /**
   * 切换图片标题状态
   */
  private toggleImageTitleStatus($container: JQuery<Element>, loading: boolean): void {
    const { titleSelector } = this.currentConfig!
    const $title = $container.find(titleSelector)

    $title.toggleClass('loading', loading)
  }

  /**
   * 从详情页获取图片信息
   */
  private async fetchImageInfoFromDetailPage(detailUrl: string): Promise<{ size: string, bulk: string }> {
    const config: ImageInfoExtractorConfig = {
      selectors: {
        size: this.currentConfig!.detailSelector.size,
        bulk: this.currentConfig!.detailSelector.bulk,
      },
      fetchConfig: this.config.fetchConfig,
    }

    const result = await this.imageInfoExtractor.extractFromDetailPage(detailUrl, config)

    if (!result.success || !result.data) {
      throw result.error || new Error('获取图片信息失败')
    }

    return {
      size: result.data.size,
      bulk: result.data.bulk,
    }
  }

  /**
   * 更新标题，添加图片信息
   */
  private updateTitleWithImageInfo($container: JQuery<Element>, size?: string, bulk?: string): void {
    const { imageSelector, titleSelector } = this.currentConfig!
    const $title = $container.find(titleSelector)

    if (!$title.length || $title.attr(this.PROCESSED_ATTR) === 'true') {
      // 切换标题为正常状态
      this.toggleImageTitleStatus($container, false)
      return
    }

    const imageDescription = $container.find(imageSelector).attr('alt') || ''
    const originalText = $title.text().trim()
    const displayText = imageDescription && imageDescription.length > originalText.length
      ? ToolKit.string.cleanText(imageDescription, this.REDUNDANT_TEXT_PATTERNS)
      : originalText
    let infoText = ''

    // 构建信息文本
    if (size) {
      const normalizeInfo = this.imageHandler.normalizeSize(size)
      infoText += `【${normalizeInfo.standardName}】`
    }
    if (bulk) {
      infoText += `【${bulk}】`
    }

    if (!infoText)
      return

    $title.html(`
      <div class="title-container">
        <span class="main-text" title="${displayText}">${displayText}</span>
        <span class="info-text" title="${size}">${infoText}</span>
      </div>
    `)
      .attr(this.PROCESSED_ATTR, 'true')
      .attr('data-original-text', originalText)

    // 切换标题为正常状态
    this.toggleImageTitleStatus($container, false)

    logger.debug(`[${this.name}] 标题已更新`, {
      original: originalText,
      newTitle: `${originalText}${infoText}`,
    })
  }

  applyConfig(config: Partial<Config>): void {
    super.updateConfig(config)

    this.applyToImages()

    logger.info(`[${this.name}] Config updated and apply`, this.config)
  }

  getStyles(): string {
    return `
${this.currentConfig
  ? `${this.currentConfig.selector} ${this.currentConfig.titleSelector}.loading {
    pointer-events: none !important;

    &::after {
      ${this.stylesService.inlinePseudo.iconMask({
        backgroundImageId: ICON_IDS.action.refresh,
        color: `var(${this.themeVarService.icon.hover})`,
      })}
      position: absolute !important;
      right: 5px !important;
      top: 50% !important;
      animation: loadingRotate 1s linear infinite !important;
    }
  }
  `
  : ''}

/* 图片样式 */
.title-container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px; /* 控制间距 */
  flex-wrap: nowrap; /* 禁止换行 */
  overflow: hidden; /* 超出隐藏 */
  
  span {
    &.main-text {
      all: unset;
      flex-shrink: 0; /* 禁止缩小 */
      white-space: nowrap; /* 禁止换行 */
      font-size: 13px;
      max-width: 50%;
      overflow: hidden;
      text-overflow: ellipsis; /* 超出显示省略号 */
    }
    
    &.info-text {
      all: unset;
      flex-shrink: 0;
      white-space: nowrap;
      font-size: 13px;
    }
  }
}
`
  }
}
